#!/bin/bash

set -e

case "$(uname -s)" in
MINGW*|CYGWIN*)
SILICE_DIR=`cygpath $SILICE_DIR`
BUILD_DIR=`cygpath $BUILD_DIR`
FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR`
FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE`
BOARD_DIR=`cygpath $BOARD_DIR`
SRC_FILE=`cygpath $1`
;;
*)
esac

# LDFLAGS for OpenGL (VGA / SPIscreen)
case "$(uname -s)" in
MINGW*)
LDFLAGS+="-LDFLAGS --static -LDFLAGS -lopengl32 -LDFLAGS -lglfw3 -LDFLAGS -lgdi32"
;;
Darwin*)
#nproc doesn't work on mac, so alias an equivalent command
alias nproc="sysctl -n hw.logicalcpu"
#add openGL frameworks
LDFLAGS+='-LDFLAGS -framework -LDFLAGS OpenGL -LDFLAGS -framework -LDFLAGS glfw3 -LDFLAGS -pthread'
;;
*)
LDFLAGS+="-LDFLAGS -lGL -LDFLAGS -lglfw -LDFLAGS -pthread"
;;
esac

echo "build script: SILICE_DIR     = $SILICE_DIR"
echo "build script: BUILD_DIR      = $BUILD_DIR"
echo "build script: BOARD_DIR      = $BOARD_DIR"
echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR"
echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE"

if hash make 2>/dev/null; then
  export MAKE=make
else
  export MAKE=mingw32-make
fi

export PATH=$PATH:$SILICE_DIR

if [[ -n "${YOSYSHQ_ROOT}" ]]; then
  export VERILATOR_ROOT=${YOSYSHQ_ROOT}/share/verilator/
fi

if [[ -z "${VERILATOR_ROOT}" ]]; then
echo "[WARNING] **** VERILATOR_ROOT is NOT set ****"
else
echo "VERILATOR_ROOT already defined, using its value"
fi
echo "build script: VERILATOR_ROOT = $VERILATOR_ROOT"

# check Verilator support for -Wno-TIMESCALEMOD
set +e
RET=$((verilator -Wno-TIMESCALEMOD) 2>&1)
set -e
OPT="-Wno-TIMESCALEMOD"
if [[ $RET == *"Unknown warning"* ]]; then
  echo "disabling $OPT"
  OPT=""
else
  echo "using $OPT"
fi

rm -rf $BUILD_DIR/obj_dir

cd $BUILD_DIR

silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}"

if [[ ! -z "${NO_BUILD}" ]]; then
  echo "Skipping build."
  exit
fi

LIBSL_DIR=$FRAMEWORKS_DIR/../src/libs/LibSL-small/src/LibSL/
VERILATOR_LIB_DIR=$FRAMEWORKS_DIR/verilator/

echo "LIBSL_DIR is set to ${LIBSL_DIR}"

# NOTE: this below is necessary due to some wierd behaviour on some MinGW
#       installs where absolute paths generated by Verilator in its makefile
#       for include directories are incorrectly interepreted by g++.
#       Relative paths seem ok.
cp    $VERILATOR_LIB_DIR/verilator_callbacks.h .
cp -R $LIBSL_DIR .

VERILATOR_GFX_SRC=" $LIBSL_DIR/Image/ImageFormat_TGA.cpp $LIBSL_DIR/Image/Image.cpp $LIBSL_DIR/Image/tga.cpp $LIBSL_DIR/Math/Vertex.cpp $LIBSL_DIR/Math/Math.cpp $LIBSL_DIR/StlHelpers/StlHelpers.cpp $LIBSL_DIR/CppHelpers/CppHelpers.cpp $LIBSL_DIR/System/System.cpp"

VERILATOR_LIB_SRC="$VERILATOR_LIB_DIR/verilator_main.cpp $VERILATOR_LIB_DIR/verilator_data.cpp $VERILATOR_LIB_DIR/display.cpp"
VERILATOR_LIB="verilator_main"

if test -f "$1.cpp"; then
	echo ">>>>>> custom verilator framework detected <<<<<<"
	VERILATOR_LIB="verilator_custom"
	VERILATOR_LIB_SRC="$1.cpp $VERILATOR_LIB_DIR/verilator_data.cpp"
	if test -f "$1.h"; then
		cp "$1.h" custom.h
	else
		touch custom.h
	fi
else
	touch custom.h
fi

DEFINES=""
if [[ -n "${VGA}" ]]; then
  DEFINES+="-CFLAGS -DVGA "
  VERILATOR_LIB_SRC+=$VERILATOR_GFX_SRC
  VERILATOR_LIB_SRC+=" $VERILATOR_LIB_DIR/VgaChip.cpp"
fi
if [[ -n "${SDRAM}" ]]; then
  DEFINES+="-CFLAGS -DSDRAM "
  VERILATOR_LIB_SRC+=" $VERILATOR_LIB_DIR/sdr_sdram.cpp"
fi
if [[ -n "${SPISCREEN}" ]]; then
  DEFINES+="-CFLAGS -DSPISCREEN "
  VERILATOR_LIB_SRC+=$VERILATOR_GFX_SRC
  VERILATOR_LIB_SRC+=" $VERILATOR_LIB_DIR/SPIScreen.cpp"
fi
if [[ -n "${OLED}" ]]; then
  DEFINES+="-CFLAGS -DSPISCREEN "
  VERILATOR_LIB_SRC+=$VERILATOR_GFX_SRC
  VERILATOR_LIB_SRC+=" $VERILATOR_LIB_DIR/SPIScreen.cpp"
fi
if [[ -n "${PARALLEL_SCREEN}" ]]; then
  DEFINES+="-CFLAGS -DPARALLEL_SCREEN "
  VERILATOR_LIB_SRC+=$VERILATOR_GFX_SRC
  VERILATOR_LIB_SRC+=" $VERILATOR_LIB_DIR/ParallelScreen.cpp"
fi

echo "using verilator framework $VERILATOR_LIB"
echo "defines: $DEFINES"

# Verilator wants to include these but they are not generated
# fixes the issue (Verilator 5.019 devel rev v5.018-42-g2dba76a7c)
touch Vtop__pch.h.slow
touch Vtop__pch.h.fast

verilator -Wno-fatal -Wno-PINMISSING -Wno-WIDTH -O3 -cc build.v --report-unoptflat $OPT --top-module top --exe $VERILATOR_LIB_SRC -CFLAGS "-include" -CFLAGS "../verilator_callbacks.h" -CFLAGS "-include" -CFLAGS "custom.h" -CFLAGS "-I$SILICE_DIR/../frameworks/verilator/" -CFLAGS "-I../"  -CFLAGS "-I../LibSL/" -CFLAGS "-DNO_SHLWAPI" $DEFINES $LDFLAGS
cd obj_dir

$MAKE -f Vtop.mk -j$(nproc)

cd ..

if [[ -z "${NO_PROGRAM}" ]]; then
  rm -f output.txt
  ./obj_dir/Vtop | tee out.log
  # ./obj_dir/Vtop > out.log 2>&1
else
  echo "Skipping execution."
fi
